package sketch.main;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;

import randoop.util.Files;
import sketch.ast.ASTFormatter;
import sketch.ast.ASTUtils;
import sketch.generator.JUnitTestCreator;
import sketch.instrumenter.SourceCodeInstrumentingVisitor;
import sketch.instrumenter.Tracer;
import sketch.instrumenter.TracerFileReader;
import sketch.ounit.ObservationInstantiationVisitor;
import sketch.specs.SketchedMethodDeclaration;
import sketch.specs.SketchedMethodsCreator;
import sketch.util.Checker;


//XXX this class is obsoleted!

/**
 * Given a test sketch, the main workflow to produce a set of executable tests looks as follows:
 * 1. do the notation expansion (including all @ChooseOne, @ChooseAll, @Repeat notations, as
 *    well as the Values.choose(...), Values.exhaust(...) notations
 * 2. do the value replacement, to produce more unit tests
 * 3. now we get a set of tests, which contains only: (1) observe methods, (2) symbolic
 *    execution methods, and (3) random fuzzing methods
 * 4. execute the code reflectively to fill in the holes
 * */

@Deprecated
public class Main {
	
	//the main entry
	public static void main(String[] args) throws IOException {
		//the input is "a file"
		Checker.checkTrue(args.length == 1, "The length of args: " + args.length);
		String testSketchFile = args[0];
		new Main().nonStaticMain(testSketchFile);
	}
	
	public void nonStaticMain(String testSketchFile) throws IOException {
		String expansionPath = ".";
		String expansionTestName = "MainExpansionTest";
		String instrumentFileName = "./testfiles/instrument" + expansionTestName + ".java";
		String traceFilePath = "./testfiles/instrument/traceFile.txt";
		String finalOutput = "./output/" + expansionTestName;
		
		SketchedMethodsCreator creator = new SketchedMethodsCreator(testSketchFile);
		List<SketchedMethodDeclaration> sketchedMethods = creator.createSketchedMethodList();
		
		//the 1st phase, do expansion
		StringBuilder testCollection = new StringBuilder();
		for(SketchedMethodDeclaration sketchedMethod : sketchedMethods) {
			List<MethodDeclaration> methods = sketchedMethod.getMethodsAfterExpansion();
			for(MethodDeclaration m : methods) {
				m.getName().setIdentifier("test" + m.getName().getIdentifier());
				m.modifiers().add(m.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD));
				testCollection.append(ASTUtils.dumpMethodWithUnusedVarRemoved(m));
			}
		}
		CompilationUnit unit = creator.getUnit();
		String[] imports = ASTUtils.extractImportDeclarationAsString(unit);
		String afterRemoving = testCollection.toString();
	    afterRemoving = ASTFormatter.formatMethodsAndRemoveParenth(testCollection.toString());
		JUnitTestCreator.createJUnitTest(afterRemoving, ".", expansionTestName, imports);
		
		//the 2nd phase, do instrumentation
		CompilationUnit expandunit = ASTUtils.astRoot(expansionPath + "/" + expansionTestName + ".java");
		SourceCodeInstrumentingVisitor visitor = new SourceCodeInstrumentingVisitor(expandunit);
		visitor.visit(expandunit);
		File file = new File(instrumentFileName);
		//System.out.println(file.getAbsolutePath());
		file.createNewFile();
		Files.writeToFile(expandunit.toString(), file);
		
		//compile and run the file
		//Tracer.saveFile = new File(traceFilePath);
		//XXX did not compile yet
		
		//parse the file
		TracerFileReader reader = new TracerFileReader(traceFilePath);
		Map<String, Map<Integer, String>> parsingResults = reader.parse();
		ObservationInstantiationVisitor instantVisitor = new ObservationInstantiationVisitor(expandunit, parsingResults);
		instantVisitor.visit(expandunit);
		
		//output the file
		File finalOutputFile = new File(finalOutput);
		finalOutputFile.createNewFile();
		Files.writeToFile(expandunit.toString(), finalOutputFile);
	}
}